﻿namespace Sofire.Data
{
    using System;
    using System.Collections.Generic;
    using System.Data;

    /// <summary>
    /// 表示一个包含 <see cref="Sofire.Data.ExecuteEventObjectBase&lt;TCommand&gt;.Executing"/> 和 <see cref="Sofire.Data.ExecuteEventObjectBase&lt;TCommand&gt;.Executed" /> 的基类。
    /// </summary>
    /// <typeparam name="TCommand">命令的类型。</typeparam>
    public abstract class ExecuteEventObjectBase<TCommand>
        where TCommand : ExecuteCommandBase
    {
        #region Events

        /// <summary>
        /// 在引擎执行命令后发生。
        /// </summary>
        public event ExecutedEventHandler Executed;

        /// <summary>
        /// 在引擎执行命令时发生。
        /// </summary>
        public event ExecutingEventHandler Executing;

        #endregion Events

        #region Methods

        /// <summary>
        /// 表示 <see cref="Sofire.Data.ExecuteEventObjectBase&lt;TCommand&gt;.Executed"/> 事件的处理方法。
        /// </summary>
        /// <param name="type">执行的类型。</param>
        /// <param name="result">操作的返回值。</param>
        /// <param name="command">执行的命令。</param>
        /// <param name="userToken">用户自定义数据。</param>
        protected internal void OnExecuted(ExecuteType type, IResult result, TCommand command, object userToken)
        {
            this.VirtualExecuted(type, result, command, null, userToken);
            if(this.Executed != null)
            {
                this.Executed(this, new ExecutedEventArgs(type, result, command) { UserToken = userToken });
            }
        }

        /// <summary>
        /// 表示 <see cref="Sofire.Data.ExecuteEventObjectBase&lt;TCommand&gt;.Executed"/> 事件的处理方法。
        /// </summary>
        /// <param name="type">执行的类型。</param>
        /// <param name="result">操作的返回值。</param>
        /// <param name="commands">执行的命令的集合。</param>
        /// <param name="userToken">用户自定义数据。</param>
        protected internal void OnExecuted(ExecuteType type, IResult result, List<TCommand> commands, object userToken)
        {
            this.VirtualExecuted(type, result, null, commands, userToken);
            if(this.Executed != null)
            {
                this.Executed(this, new ExecutedEventArgs(type, result, commands.ToCommandList()) { UserToken = userToken });
            }
        }

        /// <summary>
        /// 表示 <see cref="Sofire.Data.ExecuteEventObjectBase&lt;TCommand&gt;.Executing"/> 事件的处理方法。
        /// </summary>
        /// <param name="type">执行的类型。</param>
        /// <param name="command">执行的命令。</param>
        /// <returns>返回用户自定义数据。</returns>
        protected internal object OnExecuting(ExecuteType type, TCommand command)
        {
            var userToken = this.VirtualExecuting(type, command, null);
            if(this.Executing != null)
            {
                var e = new ExecutingEventArgs(type, command) { UserToken = userToken };
                this.Executing(this, e);
                return e.UserToken;
            }
            return null;
        }

        /// <summary>
        /// 表示 <see cref="Sofire.Data.ExecuteEventObjectBase&lt;TCommand&gt;.Executing"/> 事件的处理方法。
        /// </summary>
        /// <param name="type">执行的类型。</param>
        /// <param name="commands">执行的命令的集合。</param>
        /// <returns>返回用户自定义数据。</returns>
        protected internal object OnExecuting(ExecuteType type, List<TCommand> commands)
        {
            var userToken = this.VirtualExecuting(type, null, commands);
            if(this.Executing != null)
            {
                var e = new ExecutingEventArgs(type, commands.ToCommandList()) { UserToken = userToken };
                this.Executing(this, e);
                return e.UserToken;
            }
            return null;
        }

        /// <summary>
        /// 表示 <see cref="Sofire.Data.ExecuteEventObjectBase&lt;TCommand&gt;.Executed" /> 事件的处理方法。
        /// <para><paramref name="command"/> 或 <paramref name="commands"/> 必然有一个为 null 值。</para>
        /// </summary>
        /// <param name="type">执行的类型。</param>
        /// <param name="result">操作的返回值。</param>
        /// <param name="command">执行的命令。</param>
        /// <param name="commands">执行命令的集合。</param>
        /// <param name="userToken">用户自定义数据。</param>
        protected virtual void VirtualExecuted(ExecuteType type, IResult result, TCommand command, List<TCommand> commands, object userToken)
        {
        }

        /// <summary>
        /// 表示 <see cref="Sofire.Data.ExecuteEventObjectBase&lt;TCommand&gt;.Executing"/> 事件的处理方法。
        /// <para><paramref name="command"/> 或 <paramref name="commands"/> 必然有一个为 null 值。</para>
        /// </summary>
        /// <param name="type">执行的类型。</param>
        /// <param name="command">执行的命令。</param>
        /// <param name="commands">执行的命令的集合。</param>
        protected virtual object VirtualExecuting(ExecuteType type, TCommand command, List<TCommand> commands)
        {
            return null;
        }

        #endregion Methods
    }
}